package cn.tuling.staticsingleton;

import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

public class StaticSingletonTest implements Serializable {
    static final long serialVersionUID = 42L;

    public static void main(String[] args) throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, IOException, ClassNotFoundException {
        /*StaticSingletonTest instance = StaticSingletonTest.getInstance();
        StaticSingletonTest instance1 = StaticSingletonTest.getInstance();
        System.out.println(instance == instance1);*/

        /*System.out.println("------------反射攻击------------");
        Constructor<StaticSingletonTest> declaredConstructor =
                StaticSingletonTest.class.getDeclaredConstructor();
        StaticSingletonTest staticSingletonTest = declaredConstructor.newInstance();

        StaticSingletonTest instance = StaticSingletonTest.getInstance();
        System.out.println(staticSingletonTest == instance);*/

        System.out.println("------------序列化攻击------------");
        StaticSingletonTest instance = StaticSingletonTest.getInstance();
        ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("staticsingleton"));
        oos.writeObject(instance);

        ObjectInputStream ois = new ObjectInputStream(new FileInputStream("staticsingleton"));
        StaticSingletonTest staticSingletonTest = (StaticSingletonTest) ois.readObject();
        System.out.println(instance == staticSingletonTest);
    }

    private static class InnerSingletonHolder {
        private static StaticSingletonTest instance = new StaticSingletonTest();
    }

    private StaticSingletonTest() {
        /**
         * 防御反射攻击
         */
        /*if (InnerSingletonHolder.instance != null) {
            throw new RuntimeException("不允许创建多个实例！");
        }*/
    }

    public static StaticSingletonTest getInstance() {
        return InnerSingletonHolder.instance;
    }

    Object readResolve() throws ObjectStreamException {
        return InnerSingletonHolder.instance;
    }
}


